package com.zzl.finance.data.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzl.finance.data.constant.PaymentModeEnum;
import com.zzl.finance.data.constant.StringConstant;
import com.zzl.finance.data.constant.UserCategoryConstant;
import com.zzl.finance.data.constant.status.InstitutyStatusEnum;
import com.zzl.finance.data.constant.type.AccessProductTypeEnum;
import com.zzl.finance.data.constant.type.UserManageEnum;
import com.zzl.finance.data.dao.FinanceInstitutyDao;
import com.zzl.finance.data.dto.*;
import com.zzl.finance.data.dto.feign.UserManegeAddDto;
import com.zzl.finance.data.entity.EnterpriseEntity;
import com.zzl.finance.data.entity.FinanceInstitutyEntity;
import com.zzl.finance.data.entity.FinanceScopeEntity;
import com.zzl.finance.data.feign.UserCenterFeign;
import com.zzl.finance.data.service.EnterpriseService;
import com.zzl.finance.data.service.FinanceInstitutyService;
import com.zzl.finance.data.service.FinanceScopeService;
import com.zzl.finance.data.service.FinancialProductService;
import com.zzl.finance.data.service.common.BaseHandStatusService;
import com.zzl.general.common.constant.DeletedStatusConstant;
import com.zzl.general.common.exception.SysException;
import com.zzl.general.common.serurity.entity.User;
import com.zzl.general.common.utils.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.zzl.finance.data.constant.StringConstant.*;

/**
 * 金融机构
 *
 * @author wztsl
 * @date 2021-12-22 16:56:38
 */
@Service("financeInstitutyService")
public class FinanceInstitutyServiceImpl extends ServiceImpl<FinanceInstitutyDao, FinanceInstitutyEntity> implements FinanceInstitutyService {
    @Autowired
    private FinanceScopeService financeScopeService;
    @Autowired
    private BaseHandStatusService baseHandStatusService;
    @Autowired
    private FinancialProductService financialProductService;
    @Autowired
    private UserCenterFeign userCenterFeign;
    @Autowired
    private EnterpriseService enterpriseService;

    /**
     * 分页查询资方列表
     *
     * @param params 查询参数
     * @return 分页数据
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params, HttpSession session) {
        //排序字段：create_time
        String pageField = (String) params.get(com.zzl.general.common.constant.Constant.PAGE);
        //排序方式 order:  desc asc
        String order = (String) params.get(com.zzl.general.common.constant.Constant.ORDER);
        //接入方式
        String accessProduct = (String) params.get(StringConstant.ACCESS_PRODUCT);
        if (StringUtils.isNotBlank(accessProduct)) {
            int accessProductCode = Integer.parseInt(accessProduct);
            //接入产品查询时，将全部条件加上
            if (!AccessProductTypeEnum.PRODUCT_TYPE_ALL.getCode().equals(accessProductCode)) {
                params.put(StringConstant.ACCESS_PRODUCT_LIST
                        , Arrays.asList(AccessProductTypeEnum.PRODUCT_TYPE_ALL.getCode(), accessProductCode));
            }

        }
        //列表查询
        IPage<FinanceInstitutyPageDto> page = new Query<FinanceInstitutyPageDto>()
                .getPage(params, StringUtils.isBlank(pageField)
                        ? StringConstant.CREATE_TIME : pageField, com.zzl.general.common.constant.Constant.ASC.equals(order));
        IPage<FinanceInstitutyPageDto> list = this.baseMapper.queryPage(page, params);
        List<FinanceInstitutyPageDto> pageRecords = list.getRecords();
        //设置按钮权限
        if (!CollectionUtils.isEmpty(pageRecords)) {
            baseHandStatusService.setFinanceInstitutyOperates(pageRecords, session);
        }
        return new PageUtils(list);
    }

    /**
     * 新增
     *
     * @param financeInstitutyAddDto 新增实体
     * @param user                   当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveFinanceInstituty(FinanceInstitutyAddDto financeInstitutyAddDto, User user) throws SysException {
        //1 保存资方信息
        FinanceInstitutyEntity financeInstitutyEntity = new FinanceInstitutyEntity();
        BeanUtils.copyProperties(financeInstitutyAddDto, financeInstitutyEntity);
        financeInstitutyEntity.setCreatorId(user.getId());
        financeInstitutyEntity.setUpdaterId(user.getId());
        financeInstitutyEntity.setId(UuidUtils.UUID());
        financeInstitutyEntity.setDeletedStatus(DeletedStatusConstant.DELETED_STATUS_ON.getKey());
        //todo 上链地址
        financeInstitutyEntity.setChainAddress(UuidUtils.UUID());
        financeInstitutyEntity.setAccessProduct(AccessProductTypeEnum.PRODUCT_TYPE_BONDS.getCode());
        if (!this.save(financeInstitutyEntity)) {
            throw new SysException("A00001", "保存失败！");
        }
        //2 保存融资范围
        List<String> financingScope = financeInstitutyAddDto.getFinancingScope();
        financeScopeService.saveBatchFinanceScope(financingScope, financeInstitutyEntity.getId(), user);
        //3 保存子产品配置
        List<FinancialProductAddDto> productAddDtoList = financeInstitutyAddDto.getProductAddDtoList();
        financialProductService.saveBatchFinancialProduct(productAddDtoList, financeInstitutyEntity.getId(), user);
        //4 保存企业信息
//        5、保存管理员信息
        saveFinanceUser(financeInstitutyAddDto);
    }

    /**
     * 保存企业信息和管理员信息
     *
     * @param financeInstitutyAddDto 资方信息
     * @throws SysException 异常
     */
    private void saveFinanceUser(FinanceInstitutyAddDto financeInstitutyAddDto) throws SysException {
        //4 保存资方企业信息
        EnterpriseEntity enterprise = new EnterpriseEntity();
        enterprise.setId(UuidUtils.UUID());
        enterprise.setEnterpriseName(financeInstitutyAddDto.getInstinctyName());
        enterprise.setSocialCreditCode(financeInstitutyAddDto.getSocialCreditCode());
        enterprise.setEnterprisePhone(financeInstitutyAddDto.getEnterprisePhone());
        enterprise.setCategory(UserCategoryConstant.USER_CATEGORY_FINANCE.getKey());
        if (!enterpriseService.save(enterprise)) {
            throw new SysException("企业创建失败");
        }
        //5、保存管理员信息
        UserManegeAddDto manegeAddDto = new UserManegeAddDto();
        manegeAddDto.setEnterpriseId(enterprise.getId());
        manegeAddDto.setEnterpriseName(financeInstitutyAddDto.getInstinctyName());
        manegeAddDto.setUserAccount(financeInstitutyAddDto.getUserAccount());
        manegeAddDto.setCertificatesType("0");
        manegeAddDto.setUserCertification(financeInstitutyAddDto.getUserCertification());
        manegeAddDto.setUserManage(UserManageEnum.USER_MANAGE_ADMIN.getKey());
        manegeAddDto.setUserCategory(UserCategoryConstant.USER_CATEGORY_FINANCE.getKey());
        manegeAddDto.setUserNameCertification(financeInstitutyAddDto.getUserNameCertification());
        manegeAddDto.setUserPhone(financeInstitutyAddDto.getUserPhone());
        Result result = userCenterFeign.saveManegeUser(manegeAddDto);
        if (ResultCode.SUCCESS.getCode() != result.getCode()) {
            throw new SysException(result.getMsg());
        }
    }

    /**
     * 修改
     *
     * @param financeInstitutyUpdateDto 修改实体
     * @param user                      当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void updateFinanceInstitutyById(FinanceInstitutyUpdateDto financeInstitutyUpdateDto, User user) throws
            SysException {
        FinanceInstitutyEntity financeInstitutyEntity = new FinanceInstitutyEntity();
        BeanUtils.copyProperties(financeInstitutyUpdateDto, financeInstitutyEntity);
        financeInstitutyEntity.setUpdaterId(user.getId());
        if (!this.updateById(financeInstitutyEntity)) {
            throw new SysException("A00002", "修改失败！");
        }
    }

    /**
     * 查询企业的金融机构列表
     *
     * @param params 条件参数
     * @return 金融机构列表
     */
    @Override
    public List<FinanceInstitutyDto> getFinanceInstituty(Map<String, Object> params, User user) throws
            SysException {
        //参数校验
        this.checkParams(params, user);
        String paymentMode = (String) params.get(PAYMENT_MODE);
        String institutyId = (String) params.get(INSTITUTY_ID);
        String transferAmountString = (String) params.get(TRANSFER_AMOUNT);
        //查询金融机构的融资范围,若是全部，则查询所有金融机构
        QueryWrapper<FinanceScopeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(FinanceScopeEntity::getInstitutyId, institutyId);
        List<FinanceScopeEntity> list = financeScopeService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            throw new SysException("融资范围不存在，请联系管理员在后台设置");
        }
        String institutyScopeId = list.get(0).getInstitutyScopeId();
        //融资范围不是全部金融机构时，需要增加过滤条件
        List<String> institutyScopeIdList = new ArrayList<>();
        if (!INSTITUTY_SCOPE_ID.equals(institutyScopeId)) {
            institutyScopeIdList = list.stream().map(FinanceScopeEntity::getInstitutyScopeId).collect(Collectors.toList());
        }
        params.put(INSTITUTY_SCOPE_ID_LIST, institutyScopeIdList);
        //融资方付息，需要查询融资年化利率，核心企业付息，融资成本均显示为0
        List<FinanceInstitutyDto> financeInstitutyList = this.getBaseMapper().queryFinanceInstituty(params);

        //查询融资补充资料
        List<InstitutyDataTypeDto> dataTypeDtoList = this.getBaseMapper().queryInstitutyDataType();
        Map<String, List<InstitutyDataTypeDto>> collect = dataTypeDtoList.stream().collect(Collectors.groupingBy(InstitutyDataTypeDto::getFinanceInstitutyId));
        double transferAmount = Double.parseDouble(transferAmountString);
        financeInstitutyList.forEach(x -> {
            //计算融资成本
            if (PaymentModeEnum.PAYMENT_MODE_CORE_ENTERPRISE.getCode().equals(Integer.parseInt(paymentMode))) {
                x.setFinancingCost(0d);
                //预计到账
                x.setEstimateLoanAmount(transferAmount);
                //融资利息
                x.setAnnualizedInterest(0d);
                //平台服务费
                x.setServiceChage(0d);
            } else {
                x.setFinancingCost(transferAmount * x.getFinancingCostRate());
                //预计到账
                x.setEstimateLoanAmount(transferAmount - x.getFinancingCost());
                //融资利息
                x.setAnnualizedInterest(transferAmount * x.getAnnualizedInterestRate());
                //平台服务费
                x.setServiceChage(transferAmount * x.getPlatServiceRate());
            }
            //融资补充资料
            x.setDataTypeList(collect.get(x.getId()));
        });


        return financeInstitutyList;
    }

    /**
     * 通过id获取金融机构数据
     *
     * @param id 金融机构主键
     * @return 金融机构信息
     */
    @Override
    public FinanceInstitutyInfoDto getFinanceInstitutyById(String id) throws SysException {
        FinanceInstitutyInfoDto financeInstitutyInfoDto = new FinanceInstitutyInfoDto();
        FinanceInstitutyEntity institutyEntity = this.getById(id);
        if (ObjectUtils.isEmpty(institutyEntity)) {
            throw new SysException("当前资方信息不存在");
        }
        BeanUtils.copyProperties(institutyEntity, financeInstitutyInfoDto);
        //设置子产品
        List<FinancialProductInfoDto> productByfinanceId = financialProductService.getProductByfinanceId(id, null);
        financeInstitutyInfoDto.setProductInfoDtoList(productByfinanceId);
        //设置融资范围
        List<FinanceScopeInfoDto> financeScopeByfinanceId = financeScopeService.getFinanceScopeByfinanceId(id);
        financeInstitutyInfoDto.setScopeInfoDtoList(financeScopeByfinanceId);
        return financeInstitutyInfoDto;
    }

    /**
     * 冻结/启用 资金方
     *
     * @param id   资金方id
     * @param user 用户
     */
    @Override
    public void updateStatusById(String id, User user) throws SysException {
        FinanceInstitutyEntity byId = this.getById(id);
        if (ObjectUtils.isEmpty(byId)) {
            throw new SysException("当前资方不存在");
        }
        FinanceInstitutyEntity newEntity = new FinanceInstitutyEntity();
        newEntity.setId(id);
        newEntity.setUpdaterId(user.getId());
        if (InstitutyStatusEnum.INSTITUTY_STATUS_ENABLE.getCode().equals(byId.getInstitutyStatus())) {
            newEntity.setInstitutyStatus(InstitutyStatusEnum.INSTITUTY_STATUS_STOP.getCode());
        } else {
            newEntity.setInstitutyStatus(InstitutyStatusEnum.INSTITUTY_STATUS_ENABLE.getCode());
        }

        if (!this.updateById(newEntity)) {
            throw new SysException("资方状态修改失败");
        }

    }

    /**
     * 融资范围下拉框
     *
     * @param type 接入产品，2：反向保理、3：数字债权
     * @return 融资范围下拉框
     */
    @Override
    public List<FinanceInstitutyEntity> getFinancingScope(Integer type) {
        QueryWrapper<FinanceInstitutyEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(FinanceInstitutyEntity::getAccessProduct,
                Arrays.asList(type, AccessProductTypeEnum.PRODUCT_TYPE_ALL.getCode()));
        List<FinanceInstitutyEntity> list = this.list(queryWrapper);
        if (!CollectionUtils.isEmpty(list)) {
            FinanceInstitutyEntity institutyEntity = new FinanceInstitutyEntity();
            institutyEntity.setInstinctyName("全部");
            institutyEntity.setId("0");
            list.add(0, institutyEntity);
        }
        return list;
    }

    /**
     * 参数校验
     *
     * @param params 参数
     */
    private void checkParams(Map<String, Object> params, User user) throws SysException {
        if (null == params) {
            throw new SysException("参数不能为空");
        } else if (StringUtils.isBlank((String) params.get(INSTITUTY_ID))) {
            throw new SysException("金融机构id不能为空");
        } else if (StringUtils.isBlank((String) params.get(TRANSFER_AMOUNT))) {
            throw new SysException("转让金额不能为空");
        } else if (StringUtils.isBlank((String) params.get(PAYMENT_MODE))) {
            throw new SysException("付息方式不能为空");
        } else {
            params.put(ENTERPRISE_ID, user.getEnterpriseId());
        }
    }

    @Override
    public List<FinanceInstitutyEntity> dropDownBox() {
        return lambdaQuery().eq(FinanceInstitutyEntity::getInstitutyStatus, InstitutyStatusEnum.INSTITUTY_STATUS_ENABLE.getCode()).list();
    }
}